class asyncParallelBailHook {
    events = [];
    promiseEvents = [];

    constructor() {
        console.log('asyncParallelBailHook');
    }

    tapAsync(name, cb) {
        cb = typeof cb === 'function' ? cb : (...args) => args;
        this.events.push(cb);
    }

    tapPromise(name, cb) {
        cb = typeof cb === 'function' ? cb : (...args) => args;
        this.promiseEvents.push(cb);
    }

    callAsync(...args) {
        const callAsyncEvent = args.pop();
        const len = this.events.length;
        let index = 0;
        let isExecute = false;
        const cb = (...args1) => {
            // 要是否传递参数，cb有参数提前结束，不管成功或失败
            if (args1.length && !isExecute) {
                const err = args1.shift();
                if (err === null || err === undefined || err === false) {
                    callAsyncEvent && callAsyncEvent(undefined, args1[0]);
                } else {
                    callAsyncEvent && callAsyncEvent(args1[0], undefined);
                }
                isExecute = true;
                return;
            }
            // cb没有参数，等待所有cb执行完成，在执行callAsyncEvent
            if (index++ === len - 1) {
                callAsyncEvent && callAsyncEvent();
            }
        }
        this.events.forEach((event) => event(...args, cb));
    }

    promise(...args) {
        const list = this.promiseEvents.map((event) => {
            return event(...args);
        });
        return Promise.race(list);
    }
}

module.exports = asyncParallelBailHook;